package com.platform.comm.util;

import com.google.common.base.Strings;
import com.platform.comm.util.crypto.sm3.SM3Utils;
import com.platform.comm.util.crypto.sm4.SM4Utils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * 功能描述: AES/DES加密解密类
 *
 * <pre>
 *  1. 加密过程
 * {@code
 *
 *   String content = "Tommy And Jessica.";
 *   // 编码用于安全传输
 *   String inputBase64 = bs64EncryptWithHead(idStr);
 *   // 加密获得密文
 *   String securityStr = aesEncrypt64(inputBase64);
 *
 *   2. 解密过程
 *
 *   // 对密文进行解密,获得base64编码字符串
 *   String base64Str = aesDecrypt64(securityStr);
 *   // 对base64编码解密获得原文
 *   String plainTxt = bs64DecryptWithHead(base64Str);
 * }
 * </pre>
 *
 * @author tommy create on 2019-08-20-15:34
 */
@Slf4j
public class CryptUtil {

    private static final int STRING_LENGTH = 6;

    /**
     * base64
     *
     * @param plainStr 原数据
     * @return 转换后数据
     */
    public static String bs64Encrypt(String plainStr) {
        return Base64.getEncoder().encodeToString(plainStr.getBytes());
    }

    /**
     * base64编码加入6位混淆
     *
     * @param plainStr 原数据
     * @return 转换后数据
     */
    public static String bs64EncryptWithHead(String plainStr) {
        if (plainStr == null || plainStr.length() == 0) {
            log.warn("Empty plain text");
            return null;
        }
        String headStr = RandomStringUtils.randomAlphanumeric(6);
        return headStr + Base64.getEncoder().encodeToString(plainStr.getBytes());
    }

    /**
     * base64解码
     *
     * @param base64Str base64编码
     * @return 解码后数据
     */
    public static String bs64Decrypt(String base64Str) {
        byte[] decodedBytes = Base64.getDecoder().decode(base64Str);
        return new String(decodedBytes);
    }

    /**
     * 去除混淆内容后进行base64解码
     *
     * @param base64Str 包含混淆内容base64编码
     * @return 原数据
     */
    public static String bs64DecryptWithHead(String base64Str) {
        if (Strings.isNullOrEmpty(base64Str) || base64Str.length() < STRING_LENGTH) {
            return base64Str;
        }
        String inputStr = base64Str.substring(6);
        byte[] decodedBytes = Base64.getDecoder().decode(inputStr);
        return new String(decodedBytes);
    }

    public static String aesEncrypt(String plain) {
        return Aes.encrypt(plain);
    }

    @SneakyThrows
    public static String aesDecrypt(String secure) {
        return Aes.decrypt(secure);
    }

    /**
     * SM3摘要算法
     *
     * @param plainData 原数据
     * @return 加密后数据
     */
    public static String digest(String plainData) {
        if (plainData == null || plainData.length() == 0) {
            log.warn("Empty plain text");
            return null;
        }
        return SM3Utils.encrypt(plainData);
    }

    /**
     * SM4对称加密
     *
     * @param plainData 原数据
     * @return 加密数据
     */
    public static String encryptWithSm4(String plainData) {
        if (plainData == null || plainData.length() == 0) {
            log.warn("Empty plain text");
            return null;
        }
        try {
            return SM4Utils.encodeByBase64(plainData, StandardCharsets.UTF_8.name());
        } catch (IOException e) {
            log.warn("SM4对称加密失败");
            return null;
        }
    }

    /**
     * SM4对称加密
     *
     * @param secretData 原数据
     * @return 加密数据
     */
    public static String decryptWithSm4(String secretData) {
        if (secretData == null || secretData.length() == 0) {
            log.warn("Empty plain text");
            return null;
        }
        try {
            return SM4Utils.decodeByBase64(secretData, StandardCharsets.UTF_8.name());
        } catch (IOException e) {
            log.warn("SM4对称加密失败");
            return null;
        }
    }

    /**
     * 对前端传入base64字符串进行加密
     *
     * @param base64Str 传入base64编码字符串
     * @return aes加密后密文
     */
    public static String sm4Encrypt64(String base64Str) {
        String plainTxt = bs64DecryptWithHead(base64Str);
        return encryptWithSm4(plainTxt);
    }

    /**
     * 对数据库中密文进行解密并转为base64编码返回前端
     *
     * @param secretData aes加密密文
     * @return base64编码字符串
     */
    public static String sm4Decrypt64(String secretData) {
        String plainTxt = decryptWithSm4(secretData);
        return bs64EncryptWithHead(plainTxt);
    }

    public static void main(String[] args) {
        System.out.println("明文");
        System.out.println(CryptUtil.aesEncrypt("明文"));
        System.out.println(CryptUtil.aesDecrypt("V05c0nCZ4IHkM1Kw6I7P2w=="));

        System.out.println("base64编码=" + bs64EncryptWithHead("xzkingdeejava"));
        System.out.println("base64解码=" + bs64DecryptWithHead("5OSBJhslqBlEiQl4CQ8QaZfzPGJP6Rrw96S0axOlRvs="));
    }
}
